<template>
  <div class="flex flex-col w-full h-full bg-white dark:bg-slate-900">
    <div class="flex items-center justify-between px-5 py-4 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-slate-800">
      <h3 class="m-0 text-lg font-semibold text-gray-800 dark:text-white">{{ t('knowledgeGraph.title') }}</h3>
      <div class="flex flex-col gap-1 md:flex-row md:gap-2">
        <el-button-group>
          <el-button size="small" @click="resetGraph" class="!border-gray-300 hover:!border-blue-400">
            <el-icon><Refresh /></el-icon>
            {{ t('knowledgeGraph.reset') }}
          </el-button>
          <el-button size="small" @click="centerGraph" class="!border-gray-300 hover:!border-blue-400">
            <el-icon><Aim /></el-icon>
            {{ t('knowledgeGraph.center') }}
          </el-button>
          <el-button size="small" @click="exportGraph" class="!border-gray-300 hover:!border-blue-400">
            <el-icon><Download /></el-icon>
            {{ t('knowledgeGraph.export') }}
          </el-button>
        </el-button-group>
      </div>
    </div>
    
    <div class="flex gap-5 px-5 py-3 border-b border-gray-200 bg-gray-25 dark:bg-slate-750 dark:border-gray-700" v-if="graphStats">
      <div class="flex items-center gap-2">
        <span class="text-sm text-gray-500 dark:text-gray-400">{{ t('knowledgeGraph.nodes') }}:</span>
        <span class="text-base font-semibold text-blue-500 dark:text-blue-400">{{ graphStats.nodeCount }}</span>
      </div>
      <div class="flex items-center gap-2">
        <span class="text-sm text-gray-500 dark:text-gray-400">{{ t('knowledgeGraph.relationships') }}:</span>
        <span class="text-base font-semibold text-blue-500 dark:text-blue-400">{{ graphStats.linkCount }}</span>
      </div>
    </div>
    
    <div 
      ref="graphContainer" 
      class="relative flex-1 w-full h-full overflow-hidden border border-gray-200 rounded min-h-96 bg-gray-50 dark:bg-slate-800 dark:border-gray-700"
      v-loading="loading"
      :element-loading-text="t('knowledgeGraph.loading')"
    ></div>
    
    <!-- 节点详情弹窗 -->
    <el-dialog 
      v-model="nodeDetailVisible" 
      :title="t('knowledgeGraph.nodeDetail') + ' ID: ' + selectedNode?.id"
      width="700px"
      max-height="80vh"
      :append-to-body="true"
      :z-index="10000"
    >
      <div v-loading="nodeDetailLoading" class="py-3">
        <!-- 基本节点信息 -->
        <div v-if="selectedNode" class="mb-6">
          <div class="mb-4 leading-relaxed" v-if="selectedNode.labels && selectedNode.labels.length">
            <strong class="mr-2 text-gray-800 dark:text-white">{{ t('knowledgeGraph.labels') }}:</strong>
            <el-tag 
              v-for="label in selectedNode.labels" 
              :key="label" 
              size="small" 
              class="ml-1"
            >{{ label }}</el-tag>
          </div>
        </div>

        <!-- API获取的详细信息 -->
        <div v-if="nodeDetailData" class="space-y-4">
          <!-- Labels -->
          <div class="mb-4 leading-relaxed" v-if="nodeDetailData.labels && nodeDetailData.labels.length">
            <strong class="mr-2 text-gray-800 dark:text-white">{{ t('knowledgeGraph.labels') }}:</strong>
            <el-tag 
              v-for="label in nodeDetailData.labels" 
              :key="label" 
              size="small" 
              class="ml-1"
              type="success"
            >{{ label }}</el-tag>
          </div>

          <!-- Properties -->
          <div v-if="nodeDetailData.properties" class="mb-4">
            <strong class="block mb-2 mr-2 text-gray-800 dark:text-white">{{ t('knowledgeGraph.properties') }}:</strong>
            <div class="p-4 border border-gray-200 rounded-md bg-gray-50 dark:bg-gray-800 dark:border-gray-600">
              <div 
                v-for="(value, key) in nodeDetailData.properties" 
                :key="key" 
                class="mb-3 last:mb-0"
              >
                <div class="flex flex-col gap-1 sm:flex-row sm:items-start sm:gap-3">
                  <span class="text-sm font-medium text-gray-500 dark:text-gray-400 min-w-32">{{ key }}:</span>
                  <div class="flex-1">
                    <!-- 特殊处理文本内容 -->
                    <div 
                      v-if="String(key) === 'text'" 
                      class="p-3 overflow-y-auto text-sm leading-relaxed text-gray-800 bg-white border border-gray-200 rounded dark:text-white dark:bg-gray-700 dark:border-gray-500 max-h-40"
                    >
                      {{ value }}
                    </div>
                    <!-- 普通属性 -->
                    <span 
                      v-else 
                      class="text-sm text-gray-800 break-all dark:text-white"
                    >{{ value }}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- 无数据提示 -->
        <div 
          v-else-if="!nodeDetailLoading" 
          class="py-8 text-center text-gray-500 dark:text-gray-400"
        >
          <el-icon class="mb-2 text-2xl"><Warning /></el-icon>
          <p>{{ t('knowledgeGraph.noDetailData') }}</p>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { Refresh, Aim, Download, Warning } from '@element-plus/icons-vue';
import * as d3 from 'd3';
import { getNodeText } from '/@/api/knowledge/aiDocument';
import { createMockNodeDetail } from './simpleData';

interface GraphNode {
  id: string;
  label?: string;
  labels?: string[];
  properties?: Record<string, any>;
  group?: string;
  x?: number;
  y?: number;
  fx?: number | null;
  fy?: number | null;
}

interface GraphLink {
  id?: string;
  source: string | GraphNode;
  target: string | GraphNode;
  type: string;
  properties?: Record<string, any>;
}

interface GraphData {
  nodes: GraphNode[];
  links: GraphLink[];
}

const props = defineProps<{
  data: GraphData | null;
  loading?: boolean;
}>();

const emit = defineEmits<{
  nodeClick: [node: GraphNode];
  linkClick: [link: GraphLink];
}>();

const { t } = useI18n();

const graphContainer = ref<HTMLElement>();
const nodeDetailVisible = ref(false);
const selectedNode = ref<GraphNode | null>(null);
const nodeDetailData = ref<any>(null);
const nodeDetailLoading = ref(false);

// 是否使用节点详情Mock数据
const useGraphMock = import.meta.env.VITE_GRAPH_MOCK === 'true';

// 获取节点详情数据
const fetchNodeDetail = async (node: GraphNode) => {
  const nodeId = node.id;
  const datasetId = node.properties?.datasetId;
  
  try {
    nodeDetailLoading.value = true;
    
    // 如果启用了Mock数据，直接返回模拟数据
    if (useGraphMock) {
      // 模拟网络延迟
      await new Promise(resolve => setTimeout(resolve, 500));
      nodeDetailData.value = createMockNodeDetail(nodeId);
      return;
    }
    
    // 检查必要参数
    if (!nodeId || !datasetId) {
      console.warn('获取节点详情失败: 缺少必要参数', { nodeId, datasetId });
      nodeDetailData.value = null;
      return;
    }
    
    // 调用真实API
    const response = await getNodeText(datasetId, nodeId);
    nodeDetailData.value = response.data || null;
  } catch (error) {
    console.error('获取节点详情失败:', error);
    
    // 如果API调用失败且启用了容错模式，可以考虑使用Mock数据作为备选
    // 这里可以根据需要添加容错逻辑
    nodeDetailData.value = null;
  } finally {
    nodeDetailLoading.value = false;
  }
};

const graphStats = computed(() => {
  if (!props.data) return null;
  return {
    nodeCount: props.data.nodes.length,
    linkCount: props.data.links.length
  };
});

let svg: d3.Selection<SVGSVGElement, unknown, null, undefined>;
let simulation: d3.Simulation<GraphNode, GraphLink>;
let zoom: d3.ZoomBehavior<SVGSVGElement, unknown>;
let g: d3.Selection<SVGGElement, unknown, null, undefined>;

const width = ref(800);
const height = ref(600);

// 现代化颜色配置
const colors = d3.scaleOrdinal([
  '#3b82f6', // blue-500
  '#10b981', // emerald-500
  '#f59e0b', // amber-500
  '#ef4444', // red-500
  '#8b5cf6', // violet-500
  '#06b6d4', // cyan-500
  '#84cc16', // lime-500
  '#f97316', // orange-500
  '#ec4899', // pink-500
  '#6366f1'  // indigo-500
]);

// 检查是否为深色模式
const isDarkMode = () => {
  return document.documentElement.classList.contains('dark');
};

// 动态更新深色模式样式
const updateDarkModeStyles = () => {
  if (!svg) return;
  
  const dark = isDarkMode();
  
  // 更新 SVG 背景
  svg.style("background", dark ? "#1f2937" : "#f9fafb");
  
  // 更新连线样式
  svg.selectAll(".link")
    .attr("stroke", dark ? "#6b7280" : "#9ca3af");
  
  // 更新连线标签样式
  svg.selectAll(".link-label")
    .attr("fill", dark ? "#9ca3af" : "#4b5563")
    .style("text-shadow", dark ? "1px 1px 2px rgba(0, 0, 0, 0.8)" : "1px 1px 2px rgba(255, 255, 255, 0.8)");
};

// 响应式样式更新
const updateResponsiveStyles = () => {
  if (!svg) return;
  
  const isMobile = window.innerWidth <= 768;
  
  // 更新节点大小
  svg.selectAll(".node")
    .attr("r", isMobile ? 20 : 24);
    
  // 更新节点标签字体大小
  svg.selectAll(".node-label")
    .attr("font-size", isMobile ? "10px" : "12px");
    
  // 更新连线标签字体大小
  svg.selectAll(".link-label")
    .attr("font-size", isMobile ? "10px" : "12px");
};

const initGraph = async () => {
  if (!graphContainer.value || !props.data) {
    return;
  }
  
  // 清空之前的图形
  d3.select(graphContainer.value).selectAll("*").remove();
  
  const container = graphContainer.value;
  
  // 等待DOM更新并获取容器尺寸
  await nextTick();
  
  // 多次尝试获取正确的容器尺寸
  let attempts = 0;
  let containerRect = container.getBoundingClientRect();
  
  while ((containerRect.width === 0 || containerRect.height === 0) && attempts < 10) {
    await new Promise(resolve => setTimeout(resolve, 100));
    containerRect = container.getBoundingClientRect();
    attempts++;
  }
  
  // 获取容器实际尺寸，确保有足够的空间
  width.value = Math.max(containerRect.width || container.clientWidth || 800, 600);
  height.value = Math.max(containerRect.height || container.clientHeight || 600, 400);
  
  
  // 创建 SVG
  svg = d3.select(container)
    .append("svg")
    .attr("width", width.value)
    .attr("height", height.value)
    .attr("viewBox", `0 0 ${width.value} ${height.value}`)
    .style("background", isDarkMode() ? "#1f2937" : "#f9fafb");
  
  // 创建缩放行为
  zoom = d3.zoom<SVGSVGElement, unknown>()
    .scaleExtent([0.1, 4])
    .on("zoom", handleZoom);
    
  svg.call(zoom);
  
  // 创建容器组
  g = svg.append("g").attr("class", "graph-group");
  
  // 创建箭头标记
  svg.append("defs").selectAll("marker")
    .data(["end"])
    .enter().append("marker")
    .attr("id", "arrowhead")
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 30)
    .attr("refY", 0)
    .attr("orient", "auto")
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .append("path")
    .attr("d", "M0,-5L10,0L0,5")
    .attr("fill", "#6b7280");
  
  // 深拷贝数据避免修改原始数据
  const graphData = {
    nodes: props.data.nodes.map(d => ({ ...d })),
    links: props.data.links.map(d => ({ ...d }))
  };
  
  
  // 创建力导向图仿真
  simulation = d3.forceSimulation<GraphNode>(graphData.nodes)
    .force("link", d3.forceLink<GraphNode, GraphLink>(graphData.links)
      .id(d => d.id)
      .distance(150)
      .strength(0.3)
    )
    .force("charge", d3.forceManyBody().strength(-800))
    .force("center", d3.forceCenter(width.value / 2, height.value / 2))
    .force("collision", d3.forceCollide().radius(50))
    .force("x", d3.forceX(width.value / 2).strength(0.05))
    .force("y", d3.forceY(height.value / 2).strength(0.05))
    .alpha(1)
    .alphaDecay(0.01);
  
  // 绘制连线
  const linkGroup = g.append("g")
    .attr("class", "links")
    .selectAll("g")
    .data(graphData.links)
    .enter().append("g")
    .attr("class", "link-group");
    
  // 连线路径
  const links = linkGroup.append("line")
    .attr("class", "link")
    .attr("stroke", isDarkMode() ? "#6b7280" : "#9ca3af")
    .attr("stroke-opacity", 0.8)
    .attr("stroke-width", 2)
    .attr("marker-end", "url(#arrowhead)")
    .style("cursor", "pointer")
    .style("transition", "all 0.2s ease")
    .on("click", (event, d) => {
      event.stopPropagation();
      emit('linkClick', d);
    })
    .on("mouseover", function() {
      d3.select(this)
        .attr("stroke", "#3b82f6")
        .attr("stroke-width", 3);
    })
    .on("mouseout", function() {
      d3.select(this)
        .attr("stroke", isDarkMode() ? "#6b7280" : "#9ca3af")
        .attr("stroke-width", 2);
    });
    
  // 连线标签
  const linkLabels = linkGroup.append("text")
    .attr("class", "link-label")
    .attr("font-family", "system-ui, -apple-system, sans-serif")
    .attr("font-size", "12px")
    .attr("font-weight", "500")
    .attr("fill", isDarkMode() ? "#9ca3af" : "#4b5563")
    .attr("text-anchor", "middle")
    .attr("pointer-events", "none")
    .attr("dy", "-2")
    .style("text-shadow", isDarkMode() ? "1px 1px 2px rgba(0, 0, 0, 0.8)" : "1px 1px 2px rgba(255, 255, 255, 0.8)")
    .text(d => d.type || '关系');
  
  // 绘制节点
  const nodeGroup = g.append("g")
    .attr("class", "nodes")
    .selectAll("g")
    .data(graphData.nodes)
    .enter().append("g")
    .attr("class", "node-group")
    .style("cursor", "pointer")
    .call(d3.drag<SVGGElement, GraphNode>()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));
      
  // 节点外圈（阴影效果）
  nodeGroup.append("circle")
    .attr("class", "node-shadow")
    .attr("r", 26)
    .attr("fill", "rgba(0, 0, 0, 0.1)")
    .attr("cx", 2)
    .attr("cy", 2);
      
  // 节点圆圈
  nodeGroup.append("circle")
    .attr("class", "node")
    .attr("r", 24)
    .attr("fill", d => {
      const label = d.labels?.[0] || d.id;
      return colors(label);
    })
    .attr("stroke", "#ffffff")
    .attr("stroke-width", 3)
    .style("transition", "all 0.3s ease")
    .on("click", async (event, d) => {
      event.stopPropagation();
      selectedNode.value = d;
      nodeDetailVisible.value = true;
      
      // 获取节点详情数据
      await fetchNodeDetail(d);
      
      emit('nodeClick', d);
    })
    .on("mouseover", function(event, d) {
      d3.select(this)
        .attr("r", 28)
        .attr("stroke-width", 4);
      
      // 显示 tooltip
      showTooltip(event, d);
    })
    .on("mouseout", function() {
      d3.select(this)
        .attr("r", 24)
        .attr("stroke-width", 3);
      hideTooltip();
    });
    
  // 节点标签
  nodeGroup.append("text")
    .attr("class", "node-label")
    .attr("dy", ".35em")
    .attr("text-anchor", "middle")
    .attr("font-family", "system-ui, -apple-system, sans-serif")
    .attr("font-size", "12px")
    .attr("font-weight", "600")
    .attr("fill", "#ffffff")
    .attr("pointer-events", "none")
    .style("text-shadow", "1px 1px 1px rgba(0, 0, 0, 0.5)")
    .style("user-select", "none")
    .style("-webkit-user-select", "none")
    .text(d => {
      const title = d.properties?.title || d.id;
      return `#${Number(d.properties?.index) + 1}${title.length > 8 ? `${title.substring(0, 6)}...` : title}`;
    });
  
  // 如果没有节点，显示提示
  if (graphData.nodes.length === 0) {
    g.append("text")
      .attr("x", width.value / 2)
      .attr("y", height.value / 2)
      .attr("text-anchor", "middle")
      .attr("fill", "#6b7280")
      .attr("font-size", "16px")
      .text("暂无数据");
    return;
  }
  
  // 仿真更新
  simulation.on("tick", () => {
    // 更新连线位置
    links
      .attr("x1", (d: any) => (d.source as GraphNode).x!)
      .attr("y1", (d: any) => (d.source as GraphNode).y!)
      .attr("x2", (d: any) => (d.target as GraphNode).x!)
      .attr("y2", (d: any) => (d.target as GraphNode).y!);
      
    // 更新连线标签位置
    linkLabels
      .attr("x", (d: any) => ((d.source as GraphNode).x! + (d.target as GraphNode).x!) / 2)
      .attr("y", (d: any) => ((d.source as GraphNode).y! + (d.target as GraphNode).y!) / 2);
      
    // 更新节点位置
    nodeGroup.attr("transform", (d: any) => `translate(${d.x},${d.y})`);
  });
  
  // 仿真运行一段时间后自动居中
  setTimeout(() => {
    centerGraph();
    updateResponsiveStyles();
    updateDarkModeStyles();
  }, 1000);
  
  // 当仿真稳定时也居中一次
  simulation.on("end", () => {
    setTimeout(() => {
      centerGraph();
      updateResponsiveStyles();
      updateDarkModeStyles();
    }, 100);
  });
};

const showTooltip = (event: MouseEvent, d: GraphNode) => {
  // 移除现有tooltip
  d3.selectAll(".node-tooltip").remove();
  
  const tooltip = d3.select("body").append("div")
    .attr("class", "node-tooltip")
    .style("position", "absolute")
    .style("background", "rgba(17, 24, 39, 0.95)")
    .style("color", "white")
    .style("padding", "12px 16px")
    .style("border-radius", "8px")
    .style("font-size", "13px")
    .style("font-family", "system-ui, -apple-system, sans-serif")
    .style("box-shadow", "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)")
    .style("pointer-events", "none")
    .style("z-index", "1000")
    .style("max-width", "300px")
    .style("opacity", "0")
    .style("backdrop-filter", "blur(8px)")
    .style("transition", "all 0.2s ease");
    
  let tooltipContent = `<div style="font-weight: 600; margin-bottom: 4px;">${d.id}</div>`;
  
  if (d.labels && d.labels.length > 0) {
    tooltipContent += `<div style="color: #d1d5db; font-size: 12px; margin-bottom: 4px;">标签: ${d.labels.join(', ')}</div>`;
  }
  
  if (d.properties) {
    const props = Object.entries(d.properties).slice(0, 3); // 只显示前3个属性
    if (props.length > 0) {
      tooltipContent += `<div style="color: #d1d5db; font-size: 12px;">`;
      props.forEach(([key, value]) => {
        tooltipContent += `<div>${key}: ${String(value).substring(0, 50)}${String(value).length > 50 ? '...' : ''}</div>`;
      });
      tooltipContent += `</div>`;
    }
  }
  
  tooltip.html(tooltipContent);
  
  // 计算tooltip位置
  const tooltipNode = tooltip.node() as HTMLElement;
  const tooltipRect = tooltipNode.getBoundingClientRect();
  const x = Math.min(event.pageX + 15, window.innerWidth - tooltipRect.width - 20);
  const y = Math.max(event.pageY - tooltipRect.height - 10, 10);
  
  tooltip
    .style("left", x + "px")
    .style("top", y + "px")
    .transition()
    .duration(200)
    .style("opacity", "1");
};

const hideTooltip = () => {
  d3.selectAll(".node-tooltip")
    .transition()
    .duration(200)
    .style("opacity", "0")
    .remove();
};

const handleZoom = (event: d3.D3ZoomEvent<SVGSVGElement, unknown>) => {
  if (g) {
    g.attr("transform", event.transform.toString());
  }
};

const dragstarted = (event: d3.D3DragEvent<SVGGElement, GraphNode, unknown>, d: GraphNode) => {
  if (!event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
};

const dragged = (event: d3.D3DragEvent<SVGGElement, GraphNode, unknown>, d: GraphNode) => {
  d.fx = event.x;
  d.fy = event.y;
};

const dragended = (event: d3.D3DragEvent<SVGGElement, GraphNode, unknown>, d: GraphNode) => {
  if (!event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
};

const resetGraph = () => {
  if (simulation) {
    simulation.alpha(1).restart();
  }
  if (svg && zoom) {
    svg.transition().duration(750).call(
      zoom.transform,
      d3.zoomIdentity
    );
  }
};

const centerGraph = () => {
  if (!svg || !zoom) return;
  
  // 首先尝试根据当前图谱内容计算居中参数
  if (props.data?.nodes.length) {
    const nodes = props.data.nodes;
    let minX = Infinity, maxX = -Infinity;
    let minY = Infinity, maxY = -Infinity;
    let hasValidPositions = false;
    
    nodes.forEach(node => {
      if (node.x !== undefined && node.y !== undefined && isFinite(node.x) && isFinite(node.y)) {
        minX = Math.min(minX, node.x);
        maxX = Math.max(maxX, node.x);
        minY = Math.min(minY, node.y);
        maxY = Math.max(maxY, node.y);
        hasValidPositions = true;
      }
    });
    
    // 如果节点有有效位置，计算居中参数
    if (hasValidPositions && isFinite(minX) && isFinite(maxX) && isFinite(minY) && isFinite(maxY)) {
      const centerX = (minX + maxX) / 2;
      const centerY = (minY + maxY) / 2;
      const graphWidth = Math.max(maxX - minX, 200);
      const graphHeight = Math.max(maxY - minY, 200);
      
      // 计算合适的缩放比例，留出边距
      const padding = 100;
      const scale = Math.min(
        (width.value - padding * 2) / graphWidth,
        (height.value - padding * 2) / graphHeight,
        1.5 // 最大放大1.5倍
      );
      
      const translateX = width.value / 2 - centerX * scale;
      const translateY = height.value / 2 - centerY * scale;
      
      svg.transition().duration(750).call(
        zoom.transform,
        d3.zoomIdentity.translate(translateX, translateY).scale(scale)
      );
      return;
    }
  }
  
  // 如果无法获取节点位置或没有节点，使用默认居中
  svg.transition().duration(750).call(
    zoom.transform,
    d3.zoomIdentity.translate(0, 0).scale(1)
  );
};

const exportGraph = () => {
  if (!svg) return;
  
  try {
    const svgData = new XMLSerializer().serializeToString(svg.node()!);
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d")!;
    const img = new Image();
    
    canvas.width = width.value;
    canvas.height = height.value;
    
    img.onload = () => {
      ctx.fillStyle = "#ffffff";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(img, 0, 0);
      
      const link = document.createElement("a");
      link.download = "knowledge-graph.png";
      link.href = canvas.toDataURL();
      link.click();
    };
    
    img.onerror = () => {
      // 静默处理错误
    };
    
    img.src = "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData)));
  } catch (error) {
    // 静默处理错误
  }
};

const handleResize = () => {
  if (!graphContainer.value) return;
  
  const container = graphContainer.value;
  const newWidth = container.clientWidth || 800;
  const newHeight = container.clientHeight || 600;
  
  if (Math.abs(newWidth - width.value) > 10 || Math.abs(newHeight - height.value) > 10) {
    width.value = newWidth;
    height.value = newHeight;
    
    if (svg) {
      svg.attr("width", newWidth).attr("height", newHeight);
    }
    
    if (simulation) {
      simulation.force("center", d3.forceCenter(newWidth / 2, newHeight / 2));
      simulation.alpha(0.3).restart();
    }
    
    // 响应式调整节点和文字大小
    updateResponsiveStyles();
  }
};

// 监听数据变化
watch(() => props.data, (newData, oldData) => {
  if (newData && newData !== oldData) {
    // 停止旧的仿真
    if (simulation) {
      simulation.stop();
    }
    
    // 延迟初始化以确保DOM已更新和容器有正确尺寸
    setTimeout(() => {
      initGraph();
    }, 300);
  }
}, { deep: true });

// 监听loading状态
watch(() => props.loading, (loading) => {
  if (!loading && props.data) {
    setTimeout(() => {
      initGraph();
    }, 300);
  }
});

onMounted(() => {
  window.addEventListener('resize', handleResize);
  
  // 监听主题变化
  const observer = new MutationObserver(() => {
    updateDarkModeStyles();
  });
  
  observer.observe(document.documentElement, {
    attributes: true,
    attributeFilter: ['class']
  });
  
  // 如果有数据且不在加载中，延迟初始化图谱
  if (props.data && !props.loading) {
    nextTick(() => {
      setTimeout(() => {
        initGraph();
      }, 500); // 增加延迟确保抽屉完全打开
    });
  }
  
  // 清理函数
  onUnmounted(() => {
    observer.disconnect();
  });
});

onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
  if (simulation) {
    simulation.stop();
  }
  hideTooltip();
});
</script>